﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TmU220PrintHelperV2d0.Service;
using System.Threading;
using System.Net.Sockets;
using ZhangLogSysV1d0;
using TmU220PrintHelperV2d0.Entity;
using System.Collections.Concurrent;
using TmU220PrintHelperV2d0.Singleton;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

namespace TmU220PrintHelperV2d0.ControlUi
{
    /// <summary>
    /// TmU220打印机监控
    /// 基准打印速度为每行1秒
    /// </summary>
    public partial class TmU220PrinterMonitorV2d0 : UserControl
    {
        #region 基本属性
        public int PrinterId { get; set; }
        /// <summary>
        /// 打印机ip
        /// </summary>
        public string PrinterIp { get; set; }
        /// <summary>
        /// 打印机端口
        /// </summary>
        public int PrinterPort { get; set; }
        /// <summary>
        /// 打印机名称
        /// </summary>
        public string PrinterName { get; set; }
        /// <summary>
        /// 打印机汉字编码
        /// </summary>
        public string ChineseEncodingName { get; set; }
        /// <summary>
        /// 打印机字库为简体还是繁体
        /// </summary>
        public bool IsTraditional { get; set; }
        /// <summary>
        /// 设备类型
        /// </summary>
        public string DeviceType { get; set; }
        /// <summary>
        /// 打印机状态，用于更新rms_printer表的status字段 null:状态未知 0:正常 99：异常
        /// </summary>
        public int? Status { get; set; }
        public string BackupPrinterName { get; set; }
        public string FirstInfoLine { get; set; }
        public string SecondInfoLine { get; set; }
        /// <summary>
        /// 打印机监控线程
        /// </summary>
        public ThreadPrinterMonitorV2d0 ThreadPrinterMonitor = null;
        /// <summary>
        /// 指令缓冲
        /// </summary>
        public static byte[] ByteMessage = new byte[1024];
        /// <summary>
        /// 连接打印机套接字
        /// </summary>
        public TcpClient PrinterTcpClient = null;
        /// <summary>
        /// 心跳检查的超时信号量
        /// </summary>
        public ManualResetEvent PulseCheckTimeoutObject = new ManualResetEvent(false);
        /// <summary>
        /// 心跳检查定时器
        /// </summary>
        System.Threading.Timer PulseCheckTimer { get; set; }
        /// <summary>
        /// 打印机配置信息
        /// </summary>
        public rms_printer PrinterInfo { get; set; }
        /// <summary>
        /// 由打印机发出的数据缓冲
        /// </summary>
        public StringBuilder DataFromPrinter { get; set; }
        /// <summary>
        /// 状态条刷新的次数
        /// </summary>
        public int StatusBarUpdateCount { get; set; }

        //打印任务的数据队列
        private ConcurrentQueue<PrintTaskV2d0> DataQueue;
        #endregion
        #region 打印机状态
        private bool _IsConnected;
        /// <summary>
        /// 是否已与打印机连接
        /// </summary>
        public bool IsConnected
        {
            get
            {
                lock (LockIsConnected)
                {
                    return _IsConnected;
                }
            }
            set
            {
                lock (LockIsConnected)
                {
                    _IsConnected = value;
                }
            }
        }
        private object LockIsConnected = new object();
        private int _PrinterStatus;
        /// <summary>
        /// 打印机状态
        /// </summary>
        public int PrinterStatus
        {
            get
            {
                lock (LockPrinterStatus)
                {
                    return _PrinterStatus;
                }
            }
            set
            {
                lock (LockPrinterStatus)
                {
                    _PrinterStatus = value;
                }
            }
        }
        private object LockPrinterStatus = new object();

        private bool _IsPrinterReady;
        /// <summary>
        /// 打印机是否可用
        /// </summary>
        public bool IsPrinterReady
        {
            get
            {
                lock (LockIsPrinterReady)
                {
                    return _IsPrinterReady;
                }
            }
            set
            {
                lock (LockIsPrinterReady)
                {
                    _IsPrinterReady = value;
                }
            }
        }
        private object LockIsPrinterReady = new object();
        private bool _IsPaperExhausted;
        /// <summary>
        /// 是否缺纸
        /// </summary>
        public bool IsPaperExhausted
        {
            get
            {
                lock (LockIsPrinterReady)
                {
                    return _IsPaperExhausted;
                }
            }
            set
            {
                lock (LockIsPrinterReady)
                {
                    _IsPaperExhausted = value;
                }
            }
        }
        private object LockIsPaperExhausted = new object();
        private bool _IsJzgNormal;
        /// <summary>
        /// 卷纸盖是否正常（卷纸盖关闭未正常，打开为异常）
        /// </summary>
        private bool IsJzgNormal
        {
            get
            {
                lock (LockIsJzgNormal)
                {
                    return _IsJzgNormal;
                }
            }
            set
            {
                lock (LockIsJzgNormal)
                {
                    _IsJzgNormal = value;
                }
            }
        }
        private object LockIsJzgNormal = new object();
        /// <summary>
        /// 打印机忙
        /// </summary>
        private bool _IsBusy;
        public bool IsBusy
        {
            get
            {
                lock (LockIsBusy)
                {
                    return _IsBusy;
                }
            }
            set
            {
                lock (LockIsBusy)
                {
                    _IsBusy = value;
                }
            }
        }
        private object LockIsBusy = new object();
        /// <summary>
        /// 打印机是否处于活动状态，如果连续3次无法连接，则认为该打印机处于休眠状态，不再对其进行检测
        /// </summary>
        private bool _IsActive;
        public bool IsActive
        {
            get
            {
                lock (LockIsActive)
                {
                    return _IsActive;
                }
            }
            set
            {
                lock (LockIsActive)
                {
                    _IsActive = value;
                }
            }
        }
        private object LockIsActive = new object();

        /// <summary>
        /// 打印速度，每行用时，单位秒
        /// </summary>
        public Double BasePrintSpeed { get; set; }
        #endregion
        #region 对外发布的事件
        /// <summary>
        /// 打印机状态改变事件
        /// </summary>
        public event EventHandler<PrinterStatusV2d0> PrinterStatusEvent = null;
        /// <summary>
        /// 打印任务完成事件
        /// </summary>
        public event EventHandler<PrintTaskV2d0> PrintCompleteEvent = null;
        /// <summary>
        /// 打印任务错误事件
        /// </summary>
        public event EventHandler<PrintTaskV2d0> PrintErrorEvent = null;
        #endregion
        public TmU220PrinterMonitorV2d0()
        {
            InitializeComponent();
            PrinterId = 0;
            PrinterIp = "192.168.3.99";
            PrinterPort = 9100;
            PrinterTcpClient = null;
            PrinterStatus = 0;
            IsConnected = false;
            IsPrinterReady = false;
            IsPaperExhausted = false;
            IsBusy = false;
            BasePrintSpeed = 1;
            IsTraditional = true;
            ChineseEncodingName = "Big5";
            BackupPrinterName = string.Empty;
            PrinterInfo = new rms_printer();
            DataQueue = new ConcurrentQueue<PrintTaskV2d0>();
            DataFromPrinter = new StringBuilder();
            Status = null;
            DeviceType = "TM-U220";

        }
        public TmU220PrinterMonitorV2d0(rms_printer pInfo)
        {
            InitializeComponent();
            PrinterId = pInfo.id;
            PrinterIp = pInfo.ip;
            PrinterPort = pInfo.port.HasValue?pInfo.port.Value:9100;
            PrinterTcpClient = null;
            PrinterName = pInfo.printername;
            PrinterStatus = 0;
            IsConnected = false;
            IsPrinterReady = false;
            IsPaperExhausted = false;
            BackupPrinterName = pInfo.backup_printer;
            PrinterInfo = pInfo;
            IsBusy = false;
            IsActive = true;
            BasePrintSpeed = 1;
            IsTraditional = pInfo.is_traditional.HasValue ? pInfo.is_traditional.Value : true; ;
            ChineseEncodingName = pInfo.print_font;
            DataQueue = new ConcurrentQueue<PrintTaskV2d0>();
            DataFromPrinter = new StringBuilder();
            Status = null;
            FirstInfoLine = string.Format("{0}({1})", pInfo.name1, pInfo.printername);
            DeviceType = pInfo.device_type;
        }
        /// <summary>
        /// 添加任务到队列
        /// </summary>
        /// <param name="printTask"></param>
        public bool AddPrintTaskToQueue(PrintTaskV2d0 printTask)
        {
            bool result = false;
            try
            {
                //打印机已连接，且打印机就绪时才能添加任务
                if (IsConnected && IsPrinterReady)
                {
                    DataQueue.Enqueue(printTask);
                    result = true;
                }
            }
            catch(Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }
            return result;
        }
        /// <summary>
        /// 卸载队列中的所有任务
        /// </summary>
        /// <returns></returns>
        public List<PrintTaskV2d0> UnloadPrintTaskFromQueue()
        {
            List<PrintTaskV2d0> resultList = new List<PrintTaskV2d0>();
            try
            {
                PrintTaskV2d0 task;
                if (!IsConnected | !IsPrinterReady)
                {
                    while (DataQueue.TryDequeue(out task))
                    {
                        resultList.Add(task);
                    }
                }
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }
            return resultList;
        }

        /// <summary>
        /// 开始运行
        /// </summary>
        public void StartRunning()
        {
            ThreadPrinterMonitor = new ThreadPrinterMonitorV2d0();
            ThreadPrinterMonitor.Running = true;
            ThreadPrinterMonitor.PrinterName = PrinterName;
            ThreadPrinterMonitor.PrinterIp = PrinterIp;
            ThreadPrinterMonitor.PrinterPort = PrinterPort;
            ThreadPrinterMonitor.PrintTaskQueue = DataQueue;
            ThreadPrinterMonitor.PrinterStatusEvent += ProcPrinterStatusEvent;
            ThreadPrinterMonitor.PrintCompleteEvent += ProcPrintCompleteEvent;
            ThreadPrinterMonitor.PrintErrorEvent += ProcPrintErrorEvent;
            ThreadPrinterMonitor.FontLibraryEncodingName = ChineseEncodingName;
            ThreadPrinterMonitor.IsTraditional = IsTraditional;
            ThreadPrinterMonitor.Init();
            ThreadPrinterMonitor.StartThread();

        }
        /// <summary>
        /// 停止运行
        /// </summary>
        public void StopRunning()
        {
            ThreadPrinterMonitor.PrinterStatusEvent -= ProcPrinterStatusEvent;
            ThreadPrinterMonitor.PrintCompleteEvent -= ProcPrintCompleteEvent;
            ThreadPrinterMonitor.PrintErrorEvent -= ProcPrintErrorEvent;
            ThreadPrinterMonitor.StopThread();
        }
        /// <summary>
        /// 处理打印机状态事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="printerStatus"></param>
        public void ProcPrinterStatusEvent(object sender, PrinterStatusV2d0 printerStatus)
        {
            try
            {
                // 发布事件
                if (PrinterStatusEvent != null) PrinterStatusEvent(this, printerStatus);

                if ((IsConnected != printerStatus.IsConnected) && (IsPrinterReady != printerStatus.IsPrinterReady))
                {
                    //如果打印机状态改变，才将状态写入rms_printer数据表status字段
                }
                IsConnected = printerStatus.IsConnected;
                IsBusy = printerStatus.IsBusy;
                IsPrinterReady = printerStatus.IsPrinterReady;
                IsJzgNormal = printerStatus.IsJzgNormal;
                UpdateStatusBar(printerStatus);
                if (IsConnected && IsPrinterReady)
                {
                    Status = 0;
                }
                else Status = 99;
                HotchPotchV2d0.UpdatePrinterTable(PrinterId, Status.Value);
            }
            catch(Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }

        }
        /// <summary>
        /// 处理打印完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="printTask"></param>
        public void ProcPrintCompleteEvent(object sender, PrintTaskV2d0 printTask)
        {
            // 发布事件
            if (PrintCompleteEvent != null) PrintCompleteEvent(this, printTask);
            try
            {
                //将对应记录的status字段设置为1
                rms_order_print_main printMain = printTask.DataOfPrintTask;
                JObject jsonObject = new JObject {{ "status", "1" } ,
                                            { "printtime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") },
                                            { "act_printer", PrinterName }
                                        };
                string jsonStringOfData = JsonConvert.SerializeObject(jsonObject);
                bool result = UpdateDataKeyValueDataNetSingletonV1d0.Instance.Run("rms_order_print_main", "id", printMain.id.ToString(), jsonStringOfData);

                //printMain.status = 1;
                //printMain.printtime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                //printMain.act_printer = PrinterName;
                //UpdateDataKeyValueDataNetSingletonV1d0.Instance.Run<rms_order_print_main>("id", printMain.id.ToString(), printMain);
                //更新接口暂时不支持中文
                //HotchPotchV2d0.UpdatePrintMainTableWhenTaskPrintComplete(printTask.DataOfPrintTask.id,PrinterName);
                UpdateStatusBarCountOfQueue(DataQueue.Count);
            }
            catch(Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }
            //写日志
        }
        /// <summary>
        /// 处理打印错误事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="printTask"></param>
        public void ProcPrintErrorEvent(object sender, PrintTaskV2d0 printTask)
        {
            // 发布事件
            if (PrintErrorEvent != null) PrintErrorEvent(this, printTask);
            //记录打印错误
            SimpleLoger.Instance.PrintRecord("打印错误->" + HotchPotchV2d0.GetPrintRecordLogStr(printTask));
            //将该任务重新写回主打印队列，由系统分派给其备用打印机
            //如果任务打印过程中，打印机出现错误，则该打印任务被丢弃不再进行打印
            //DataQueue.Enqueue(printTask);
            //写日志
        }



        /// <summary>
        /// 在主线程刷新UI
        /// </summary>
        /// <param name="byteMessage"></param>
        public void ProcessMessageInMainThread(byte[] byteMessage)
        {
            try
            {
                if (this.IsDisposed)
                    return;

                if (!this.InvokeRequired)
                {
                    //ProcessMessage(byteMessage);
                    return;
                }
                //MethodInvoker 需要无参数的函数，所以使用匿名委托将带参数的函数转换为不带参数的委托
                this.Invoke(
                    new MethodInvoker(
                        delegate ()
                        {
                            //ProcessMessage(byteMessage);
                        }
                    )
                );
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }
        }

        private void UpdateStatusBarCountOfQueue(int countOfQueue)
        {
            this.toolStripStatusLabelQueueCount.Text = countOfQueue.ToString("D3");
        }

        /// <summary>
        /// 更新状态栏 ip_port,is_online,is_ready
        /// </summary>
        private void UpdateStatusBar(PrinterStatusV2d0 printerStatus)
        {
            this.Invoke(new Action(() =>
            {

                toolStripStatusLabelIpPort.Text = PrinterIp;
                if (printerStatus.IsConnected)
                {
                    toolStripStatusLabelOnline.Text = "联机";
                }
                else
                {
                    toolStripStatusLabelOnline.Text = "未联机";
                }

                if (printerStatus.IsPrinterReady)
                {
                    toolStripStatusLabelReady.Text = "正常";
                }
                else
                {
                    toolStripStatusLabelReady.Text = "故障";
                }

                if (printerStatus.IsJzgNormal)
                {
                    toolStripStatusLabelJzgStatus.Text = "卷纸盖正常";
                }
                else
                {
                    toolStripStatusLabelJzgStatus.Text = "卷纸盖打开";
                }
                if(printerStatus.IsConnected&& printerStatus.IsPrinterReady && printerStatus.IsJzgNormal)
                {
                    this.statusStrip1.BackColor = Color.FromName("Control");
                    this.statusStrip1.BackColor = Color.FromArgb(0xBB, 0xFF, 0x99);
                }
                else
                {
                    this.statusStrip1.BackColor = Color.FromArgb(0xFF,0x80,0x80);
                }
                StatusBarUpdateCount++;
                if (StatusBarUpdateCount % 4 == 0) this.toolStripStatusLabelPulseCheck.Text = @"--";
                else if (StatusBarUpdateCount % 4 == 1) this.toolStripStatusLabelPulseCheck.Text = @"\";
                else if (StatusBarUpdateCount % 4 == 2) this.toolStripStatusLabelPulseCheck.Text = @"|";
                else this.toolStripStatusLabelPulseCheck.Text = @"/";
                //
            }));
        }

        /// <summary>
        /// 当打印机监控控件装载后
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TmU220PrinterMonitorV2d0_Load(object sender, EventArgs e)
        {
            IsConnected = false;
            IsPrinterReady = false;
            IsPaperExhausted = false;
            labelPlace.Text = "打印机名称:" + PrinterInfo.printername;
            labelIndex.Text="备份打印机:" + PrinterInfo.backup_printer;
            toolStripStatusLabelIpPort.Text = PrinterInfo.ip ;
            toolStripStatusLabelQueueCount.Text = "000";
            StartRunning();
        }
    }
}
